#include "gui_container.h"
#include "gui_spirit.h"
#include "gui_box.h"
#include <stdlib.h>
#include <stdio.h>
#include<assert.h>

gui_container_t *gui_container_create(gui_spirit_t *spirit)
{
    gui_container_t *container = malloc(sizeof(gui_container_t));
    if (!container)
        return NULL;
    container->spirit = spirit;
    list_init(&container->children_list);
    return container;
}

int gui_container_destroy(gui_container_t *container)
{
    if (!container)
        return -1;
    container->spirit = NULL;
    free(container);
    return 0;
}

// add spirit from sub container,only bind view and pos,no add actual spirit to container
static int gui_container_add_sub_container(gui_container_t *container, gui_spirit_t *spirit)
{
    if (!container)
        return -1;

    // don't add itself
    if (container->spirit == spirit)
        return -1;

    // spirit has been add to container
    if (list_find(&spirit->list, &container->children_list))
        return -1;

    // bind source
    gui_spirit_t *attach_spirit = (gui_spirit_t *)container->spirit;
    assert(attach_spirit);

    // set sub container all spirit pos and view
    gui_spirit_set_view(spirit, attach_spirit->view);
    gui_spirit_set_pos(spirit, attach_spirit->x + spirit->x, attach_spirit->y + spirit->y);

    // add sub container other spirit to container
    if (!list_empty(&spirit->container->children_list))
    {
        gui_spirit_t *sub_spirit=NULL;
        list_traversal_all_owner_to_next(sub_spirit, &spirit->container->children_list, list)
        {
            gui_container_add_sub_container(container, sub_spirit);
        }
    }
}

// add spirit to container and bind to container view
int gui_container_add(gui_container_t *container, gui_spirit_t *spirit)
{
    if (!container)
        return -1;

    // don't add itself
    if (container->spirit == spirit)
        return -1;

    // spirit has been presence on the container
    if (list_find(&spirit->list, &container->children_list))
        return -1;

    // add to list
    list_add_tail(&spirit->list, &container->children_list);

    // bind source
    gui_spirit_t *attach_spirit = (gui_spirit_t *)container->spirit;
    spirit->attached_container = container;

    gui_spirit_set_pos(spirit, spirit->x + attach_spirit->x, spirit->y + attach_spirit->y);
    gui_spirit_set_view(spirit, attach_spirit->view);


    // deal with sub container all spirit
    if (spirit->container)
    {
        if (!list_empty(&spirit->container->children_list))
        {
            gui_spirit_t *sub_spirit=NULL;
            list_traversal_all_owner_to_next(sub_spirit, &spirit->container->children_list, list)
            {
                gui_container_add_sub_container(container, sub_spirit);
            }
        }
    }
}

static int gui_container_remove_sub_container(gui_container_t *container, gui_spirit_t *spirit)
{
    if (!container)
        return -1;

    gui_spirit_t *tmp;
    list_traversal_all_owner_to_next(tmp, &container->children_list, list)
    {
        if (tmp == spirit)
        {
            gui_spirit_set_view(spirit, -1);

            if (tmp->container)
            {
                gui_spirit_t *sub_spirit;

                // spirit had sub container
                list_traversal_all_owner_to_next(sub_spirit, &spirit->container->children_list, list)
                {
                    gui_container_remove_sub_container(container,sub_spirit);
                }
            }
        }
    }
}

int gui_container_remove(gui_container_t *container, gui_spirit_t *spirit)
{
    if (!container)
        return -1;

    gui_spirit_t *tmp;
    list_traversal_all_owner_to_next(tmp, &container->children_list, list)
    {
        if (tmp == spirit)
        {
            list_del_init(&spirit->list);
            spirit->attached_container = NULL;
            gui_spirit_set_view(spirit, -1);

            // spirit had sub container
            if (tmp->container)
            {
                gui_spirit_t *sub_spirit;

                // remove sub contianer all spirit
                list_traversal_all_owner_to_next(sub_spirit, &spirit->container->children_list, list)
                {
                    gui_container_remove_sub_container(container, sub_spirit);
                }
            }
            return 0;
        }
    }
    return -1;
}

//from gui container doing remove all spirit and destroy object memory
int gui_container_remove_destroy_all(gui_container_t *container)
{
    if (!container)
        return -1;
    gui_spirit_t *spirit, *next;
    list_traversal_all_owner_to_next_safe(spirit, next, &container->children_list, list)
    {
        list_del_init(spirit);
        spirit->attached_container = NULL;
        gui_spirit_set_view(spirit, -1);
        gui_spirit_destroy(spirit);
    }
    return 0;
}

int gui_container_update_pos(gui_container_t *container,int x,int y)
{
    if(!container)
        return -1;
    gui_spirit_t *spirit,*next;
    list_traversal_all_owner_to_next_safe(spirit,next,&container->children_list,list)
    {
        spirit->x+=x;
        spirit->y+=y;
    }
}